﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Linq;
using System.IO;

using Html = DataCoreTechnologies.Scribe.Business.Html;
using SqlServer = DataCoreTechnologies.SqlServer;
using Business = DataCoreTechnologies.Scribe.Business;

namespace DataCoreTechnologies.Scribe
{
    internal partial class MainForm : MainFormBusiness
    {
        #region Public
        //Constructor
        public MainForm()
        {
            InitializeComponent();
            //Set the folder path this executable is currently running under
            string rootFolderPath = Application.ExecutablePath;
            int lastSlash = rootFolderPath.LastIndexOf(@"\");
            rootFolderPath = rootFolderPath.Substring(0, lastSlash + 1) + @"images\";
            rootFolderPath = rootFolderPath.Replace(@"\", @"\\");
            Business.Html.ServerDocument.RootFolderPath = rootFolderPath;
        }
        #endregion
        #region Private
        //Properties
        private System.ComponentModel.ComponentResourceManager _resources = 
               new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
        private Boolean _toolBarVisible = true;
        private Boolean _statusBarVisible = true;
        private UI.TreeNodeDocument _clickedOnNode = null;

        //Form Events
        private void frmMain_Load(object sender, EventArgs e)
        {
            SplashScreen.ShowSplashScreen();
            System.Threading.Thread.Sleep(2200);
        }
        private void btnConnect_Click(object sender, EventArgs e)
        {
           LoadServerInformationAndCreateNodes();
        }
        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            DisconnectFromServer();
        }
        private void treeServerObjects_MouseUp(object sender, MouseEventArgs e)
        {
            TreeView treeView = (TreeView)sender;
            Point p = new Point(e.X, e.Y);
            UI.TreeNodeDocument node = (UI.TreeNodeDocument)treeView.GetNodeAt(p);
            _clickedOnNode = node;

            //First make sure the user clicked on a node
            if (node != null)
            {
               #region Left Button
               //Load and expand any data if necessary
                if (e.Button == MouseButtons.Left)
                {
                    var htmlDocument = GetHtmlDocument(node);
                    SetActivePage(node);
                    if (node.Nodes.Count == 0 & htmlDocument is Business.Html.DatabaseDocument)
                    {
                       htmlDocument.RootDatabase.LoadDatabaseInformation();
                       CreateDatabasePages(node, (Business.Html.DatabaseDocument)htmlDocument);
                    }

                    if (htmlDocument.DocumentType == Business.Html.DocumentType.Database)
                    {
                       htmlDocument.ShouldDocument = !htmlDocument.ShouldDocument;
                       node.SetDatabaseCheckbox(htmlDocument.ShouldDocument);
                       UpdateStatusLabel("Database objects loaded");
                    }
                    else
                    {
                       UpdateStatusLabel("Ready");
                    }
                    webPreview.DocumentText = htmlDocument.GetHtml();
                }
                #endregion
               #region Right Button
                //Handle the displays of any necessary context menus
                else if (e.Button == MouseButtons.Right)
                {
                    TreeNode oldSelectNode = treeView.SelectedNode;

                    var htmlDocument = GetHtmlDocument(node);
                    if (htmlDocument.DocumentType == Business.Html.DocumentType.Database)
                    {
                       System.Diagnostics.Debug.WriteLine(p);
                       databaseContextMenuStrip.Show(treeView, p);
                    }                   
                    treeView.SelectedNode = oldSelectNode;
                    oldSelectNode = null;
                }
                #endregion
            }
        }
        private void webPreview_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            string url = e.Url.ToString();
            if (url.EndsWith(@"/") == true) url = url.TrimEnd(@"/".ToCharArray());
            url = url.ToLower();

            Business.Html.Document html = GetHtmlDocument(url);
            TreeNode node = GetTreeNode(url);
            SetActivePage(node);

            if (html != null && node != null) {
                webPreview.DocumentText = html.GetHtml();
                e.Cancel = true;
            }
        }
        private void treeServerObjects_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }
        private void treeServerObjects_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }
        private void treeServerObjects_KeyUp(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }
        private void btnConnectToServer_Click(object sender, EventArgs e)
        {
           LoadServerInformationAndCreateNodes();
        }
        private void btnDisconnectFromServer_Click(object sender, EventArgs e)
        {
           DisconnectFromServer();
        }
        private void btnCreateDocumentation_Click(object sender, EventArgs e)
        {
           CreateDocumentation();
        }
        
        //Methods
        private UI.TreeNodeDocument AddTreeNode(UI.TreeNodeDocument rootNode, 
            string text, Business.Html.Document htmlDocument,
            UI.TreeViewImage nodeImage)
        {
            UI.TreeNodeDocument node = new UI.TreeNodeDocument();
            node.Text = text;
            node.Image = nodeImage;
            rootNode.Nodes.Add(node);
            AddPage(node, htmlDocument);
            return node;
        }
        private void CreateDatabasePages(UI.TreeNodeDocument node, 
            Business.Html.DatabaseDocument databaseDocument)
        {
            this.Cursor = Cursors.WaitCursor;
            try
            {
                ClearPages(databaseDocument.RootDatabase);
                node.Nodes.Clear();
                
                databaseDocument.ClearHtmlPages();
                databaseDocument.CreateHtmlPages();
                //Tables
                if (Business.FilterPreferences.ShowTablesPage)
                {
                   Business.Html.TablesDocument tablesDocument = databaseDocument.TablesDocument;
                   UI.TreeNodeDocument tablesNode = AddTreeNode(node, tablesDocument.DisplayName,
                                                               tablesDocument, UI.TreeViewImage.Folder);
                   foreach (Business.Html.TableDocument tableDocument in databaseDocument.TableDocuments)
                   {
                      AddTreeNode(tablesNode, tableDocument.DisplayName,
                                  tableDocument, UI.TreeViewImage.Table);
                   }
                }
                //Views
                if (Business.FilterPreferences.ShowViewsPage)
                {
                   Business.Html.ViewsDocument viewsDocument = databaseDocument.ViewsDocument;
                   UI.TreeNodeDocument viewsNode = AddTreeNode(node, viewsDocument.DisplayName,
                                                               viewsDocument, UI.TreeViewImage.Folder);
                   foreach (Business.Html.ViewDocument viewDocument in databaseDocument.ViewDocuments)
                   {
                      AddTreeNode(viewsNode, viewDocument.DisplayName,
                                  viewDocument, UI.TreeViewImage.View);
                   }
                }
                //Stored Procedures
                if (Business.FilterPreferences.ShowStoredProceduresPage)
                {
                   Business.Html.StoredProceduresDocument storedProceduresDocument = databaseDocument.StoredProceduresDocument;
                   UI.TreeNodeDocument sProcsNode = AddTreeNode(node, storedProceduresDocument.DisplayName,
                                                   storedProceduresDocument, UI.TreeViewImage.Folder);
                   foreach (Business.Html.StoredProcedureDocument storedProcedureDocument in databaseDocument.StoredProcedureDocuments)
                   {
                      AddTreeNode(sProcsNode, storedProcedureDocument.DisplayName,
                                  storedProcedureDocument, UI.TreeViewImage.StoredProcedure);
                   }
                }
                //Functions
                if (Business.FilterPreferences.ShowFunctionsPage)
                {
                   Business.Html.FunctionsDocument functionsDocument = databaseDocument.FunctionsDocument;
                   UI.TreeNodeDocument functionsNode = AddTreeNode(node, functionsDocument.DisplayName,
                                                                   functionsDocument, UI.TreeViewImage.Folder);
                   foreach (Business.Html.FunctionDocument functionDocument in databaseDocument.FunctionDocuments)
                   {
                      AddTreeNode(functionsNode, functionDocument.DisplayName,
                                  functionDocument, UI.TreeViewImage.Function);
                   }
                }
                //Data Types
                if (Business.FilterPreferences.ShowDataTypesPage)
                {
                   Business.Html.DataTypesDocument dataTypesDocument = databaseDocument.DataTypesDocument;
                   TreeNode dataTypesNode = AddTreeNode(node, dataTypesDocument.DisplayName,
                                                       dataTypesDocument, UI.TreeViewImage.Folder);
                }
                //Schemas
                if (Business.FilterPreferences.ShowSchemasPage)
                {
                   Business.Html.SchemasDocument schemasDocument = databaseDocument.SchemasDocument;
                   TreeNode schemasNode = AddTreeNode(node, schemasDocument.DisplayName,
                                                       schemasDocument, UI.TreeViewImage.Folder);
                }
                //Columns
                if (Business.FilterPreferences.ShowColumnsPage)
                {
                   Business.Html.ColumnsDocument columnsDocument = databaseDocument.ColumnsDocument;
                   TreeNode columnsNode = AddTreeNode(node, columnsDocument.DisplayName,
                                                       columnsDocument, UI.TreeViewImage.Folder);
                }
                //Indexes
                if (Business.FilterPreferences.ShowIndexesPage)
                {
                   Business.Html.IndexesDocument indexesDocument = databaseDocument.IndexesDocument;
                   UI.TreeNodeDocument indexesNode = AddTreeNode(node, indexesDocument.DisplayName,
                                                       indexesDocument, UI.TreeViewImage.Folder);
                   foreach (Business.Html.IndexDocument indexDocument in databaseDocument.IndexDocuments)
                   {
                      AddTreeNode(indexesNode, indexDocument.DisplayName,
                                  indexDocument, UI.TreeViewImage.Index);
                   }
                }
                //Default Values
                if (Business.FilterPreferences.ShowDefaultValuesPage)
                {
                   Business.Html.DefaultValuesDocument defaultValuesDocument = databaseDocument.DefaultValuesDocument;
                   TreeNode defaultValueNode = AddTreeNode(node, defaultValuesDocument.DisplayName,
                                                           defaultValuesDocument, UI.TreeViewImage.Folder);
                }
                //Parameters
                if (Business.FilterPreferences.ShowParametersPage)
                {
                   Business.Html.ParametersDocument parametersDocument = databaseDocument.ParametersDocument;
                   TreeNode parametersNode = AddTreeNode(node, parametersDocument.DisplayName,
                                                           parametersDocument, UI.TreeViewImage.Folder);
                }
                //Triggers
                if (Business.FilterPreferences.ShowTriggersPage)
                {
                   Business.Html.TriggersDocument triggersDocument = databaseDocument.TriggersDocument;
                   UI.TreeNodeDocument triggersNode = AddTreeNode(node, triggersDocument.DisplayName,
                                                           triggersDocument, UI.TreeViewImage.Folder);

                   foreach (Business.Html.TriggerDocument triggerDocument in databaseDocument.TriggerDocuments)
                   {
                      AddTreeNode(triggersNode, triggerDocument.DisplayName,
                                  triggerDocument, UI.TreeViewImage.Function);
                   }
                }
                
                node.Expand();
            }
            catch (Exception ex)
            {
                SqlServer.Diagnostic.WriteLine("Error:" + ex.Message);
                SqlServer.Diagnostic.WriteLine("Error:" + ex.StackTrace);
                MessageBox.Show("Error: Unable to load database information", "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }
        private void LoadServerInformationAndCreateNodes()
        {
				var connectionStringBuilder = GetSqlConnectionStringBuilder();
            if (connectionStringBuilder != null)
            {
               try
               {
                  this.Cursor = Cursors.WaitCursor;
                  btnConnectToServer.Enabled = false;
                  connectToolStripMenuItem1.Enabled = false;

                  ClearPages(null);
                  //Create the server database object and load a list of databases.
                  _server = new SqlServer.Server(connectionStringBuilder);
                  _server.Connect();
                  _server.LoadDatabaseList();

                  //Create a server html document
                  var serverDocument = new Business.Html.ServerDocument(_server);
                  //Add the server node to the tree view control
                  var serverNode = new UI.TreeNodeDocument();
                  serverNode.Text = serverDocument.DisplayName;
                  serverNode.Image = UI.TreeViewImage.Server;
                  treeServerObjects.Nodes.Add(serverNode);
                  //and add a Page object for later reference
                  AddPage(serverNode, serverDocument);

                  //Load a list of databases under this server and create nodes 
                  // for each of them
                  foreach (SqlServer.Database database in _server.Databases)
                  {
                     var databaseDocument = new Business.Html.DatabaseDocument(database);
                     var dbNode = AddTreeNode(serverNode, databaseDocument.DisplayName,
                                             databaseDocument, UI.TreeViewImage.UncheckedBox);
                     //AddPage(dbNode, databaseDocument);
                  }
                  serverNode.Expand();

                  btnDisconnectFromServer.Enabled = true;
                  disconnectToolStripMenuItem1.Enabled = true;
                  btnCreateDocumentation.Enabled = true;
                  createDocumentationToolStripMenuItem.Enabled = true;

                  UpdateStatusLabel("Server database list loaded");
               }
               catch (InvalidOperationException ex)
               {
                  btnConnectToServer.Enabled = true;
                  connectToolStripMenuItem.Enabled = true;
                  SqlServer.Diagnostic.WriteLine("Error:" + ex.Message);
                  SqlServer.Diagnostic.WriteLine("Error:" + ex.StackTrace);
                  MessageBox.Show("Error: Unable to connect to server", "Error",
                                  MessageBoxButtons.OK, MessageBoxIcon.Error);
               }
               catch (SqlException ex)
               {
                  btnConnectToServer.Enabled = true;
                  connectToolStripMenuItem.Enabled = true;
                  SqlServer.Diagnostic.WriteLine("Error:" + ex.Message);
                  SqlServer.Diagnostic.WriteLine("Error:" + ex.StackTrace);
                  MessageBox.Show("Error: Unable to connect to server", "Error",
                                  MessageBoxButtons.OK, MessageBoxIcon.Error);
               }
                finally
                {
                    this.Cursor = Cursors.Default;
                }
            }
        }
        private void DisconnectFromServer()
        {
            SqlServer.Diagnostic.Close();

            _server.Disconnect();
            _server.RemoveDatabases(null);
            ClearPages(null);
            treeServerObjects.Nodes.Clear();
            webPreview.DocumentText = "";

            btnDisconnectFromServer.Enabled = false;
            disconnectToolStripMenuItem1.Enabled = false;
            btnConnectToServer.Enabled = true;
            connectToolStripMenuItem1.Enabled = true;
            btnCreateDocumentation.Enabled = false;
            createDocumentationToolStripMenuItem.Enabled = false;
        }
        private void CreateDocumentation()
        {
           int databaseCount = (from page in Pages
                                where page.htmlDocument.DocumentType == Business.Html.DocumentType.Database
                                    && page.htmlDocument.ShouldDocument
                                select page).Count();
           if (databaseCount == 0)
           {
              MessageBox.Show("Error: No databases were selected", "Error",
                              MessageBoxButtons.OK, MessageBoxIcon.Error);
           }
           else
           {
              OutputForm output = new OutputForm();

              var databases = Pages
                               .Where(page => page.Type == Html.DocumentType.Database
                                                        && page.htmlDocument.ShouldDocument)
                               .Select(page => page.htmlDocument.RootDatabase);

              Business.Page serverPage = Pages
                                    .Where(page => page.Type == Html.DocumentType.Server)
                                    .Single<Business.Page>();
              List<Business.Page> documentedPages = Pages
                                    .Where(page => databases.Contains(page.htmlDocument.RootDatabase))
                                    .ToList<Business.Page>();

              documentedPages.Add(serverPage);
              output.Pages = documentedPages;

              output.ShowDialog();
              output = null;
           }
        }
        private void UpdateStatusLabel(string label)
        {
           toolStripStatusLabel1.Text = label;
        }
        private void ResizeMainPanel()
        {
           int menuHeight = topMenuStrip.Height;
           int toolBarHeight = topToolStrip.Visible ? topToolStrip.Height : 0;
           int topHeight = menuHeight + toolBarHeight + 3;

           int bottomHeight = mainStatusStrip.Visible ? mainStatusStrip.Height : 0;

           splitContainer1.Top = topHeight;
           splitContainer1.Height = this.ClientSize.Height - topHeight - bottomHeight;
        }
        #endregion
        #region Menu Events
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutForm about = new AboutForm();
            about.ShowDialog();
            about.Dispose();
        }
        private void colorOptionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorOptionsForm colorOptions = new ColorOptionsForm();
            colorOptions.TopMenuColor = Business.ColorPreferences.Default;
            colorOptions.SelectedItemColor = Business.ColorPreferences.HighlightedItem;
            colorOptions.EvenRowColor = Business.ColorPreferences.EvenRow;

            colorOptions.ShowDialog();
            if (colorOptions.DialogResult != DialogResult.Cancel)
            {
                Business.ColorPreferences.Default = colorOptions.TopMenuColor;
                Business.ColorPreferences.HighlightedItem = colorOptions.SelectedItemColor;
                Business.ColorPreferences.EvenRow = colorOptions.EvenRowColor;

                InvalidatePages(null);
                if (treeServerObjects.SelectedNode != null)
                    webPreview.DocumentText = GetHtmlDocument(treeServerObjects.SelectedNode).GetHtml();
            }
        }
        private void statusBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
           _statusBarVisible = !_statusBarVisible;
           mainStatusStrip.Visible = _statusBarVisible;
           if (_statusBarVisible)
              statusBarToolStripMenuItem.Image = ((System.Drawing.Image)(_resources.GetObject("statusBarToolStripMenuItem.Image")));
           else
              statusBarToolStripMenuItem.Image = null;

           ResizeMainPanel();
        }
        private void filtersToolStripMenuItem_Click(object sender, EventArgs e)
        {
           FiltersForm filterForm = new FiltersForm(Business.FilterPreferences.GetFilterPreferences());
           if (filterForm.ShowDialog() == DialogResult.OK)
           {
               Business.FilterPreferences.SaveFilterPreferences(filterForm.FilterPreferences);
               InvalidatePages(null);

               var dbPages = from page in _pages
                             where page.Type == Html.DocumentType.Database
                             select page;
               var dbArray = dbPages.ToArray<Business.Page>();

               foreach (Business.Page page in dbArray)
               {
                  _pages.RemoveAll(p => p.Type != Html.DocumentType.Database
                                        && p.htmlDocument.RootDatabase == page.htmlDocument.RootDatabase);
                  page.treeNode.Nodes.Clear();
                  if (page.htmlDocument.RootDatabase.LoadedOn != null)
                     CreateDatabasePages((UI.TreeNodeDocument)page.treeNode, (Html.DatabaseDocument)page.htmlDocument);
               }
               if (treeServerObjects.SelectedNode != null)
                  webPreview.DocumentText = GetHtmlDocument(treeServerObjects.SelectedNode).GetHtml();
           }
           filterForm.Dispose();
        }
        private void connectToolStripMenuItem1_Click(object sender, EventArgs e)
        {
           LoadServerInformationAndCreateNodes();
        }
        private void disconnectToolStripMenuItem1_Click(object sender, EventArgs e)
        {
           DisconnectFromServer();
        }
        private void menuBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
           _toolBarVisible = !_toolBarVisible;
           topToolStrip.Visible = _toolBarVisible;
           if (_toolBarVisible)
              menuBarToolStripMenuItem.Image = ((System.Drawing.Image)(_resources.GetObject("menuBarToolStripMenuItem.Image")));
           else
              menuBarToolStripMenuItem.Image = null;

           ResizeMainPanel();
        }
        private void createDocumentationToolStripMenuItem_Click(object sender, EventArgs e)
        {
           CreateDocumentation();
        }
        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
           var htmlDocument = GetHtmlDocument(_clickedOnNode);
           htmlDocument.RootDatabase.LoadDatabaseInformation();
           CreateDatabasePages(_clickedOnNode, (Business.Html.DatabaseDocument)htmlDocument);
           htmlDocument.ShouldDocument = true;
           _clickedOnNode.SetDatabaseCheckbox(htmlDocument.ShouldDocument);
           webPreview.DocumentText = htmlDocument.GetHtml();
        }
        #endregion
    }
}
